#include "utils/object_pool.h"
#include <gtest/gtest.h>
#include <thread>
#include <vector>
#include <chrono>
#include <memory>

using namespace hft::utils;

// 用于测试的简单类
class TestObject {
public:
    TestObject() noexcept : value_(0) {}
    void setValue(int v) noexcept { value_ = v; }
    int getValue() const noexcept { return value_; }
private:
    int value_;
};

// 基本功能测试
TEST(ObjectPoolTest, BasicOperations) {
    ObjectPool<TestObject, 4> pool;
    
    // 初始状态检查
    EXPECT_EQ(pool.capacity(), 4);
    EXPECT_EQ(pool.available(), 4);

    // 获取对象
    auto obj1 = pool.acquire();
    ASSERT_TRUE(obj1.has_value());
    EXPECT_EQ(pool.available(), 3);

    // 使用对象
    obj1.value()->setValue(42);
    EXPECT_EQ(obj1.value()->getValue(), 42);

    // 释放对象（通过作用域）
    {
        auto obj2 = pool.acquire();
        ASSERT_TRUE(obj2.has_value());
        EXPECT_EQ(pool.available(), 2);
    }
    EXPECT_EQ(pool.available(), 3);
}

// 边界条件测试
TEST(ObjectPoolTest, BoundaryConditions) {
    ObjectPool<TestObject, 2> pool;

    // 获取所有对象
    auto obj1 = pool.acquire();
    auto obj2 = pool.acquire();
    ASSERT_TRUE(obj1.has_value());
    ASSERT_TRUE(obj2.has_value());
    
    // 池已满，应该无法获取更多对象
    auto obj3 = pool.acquire();
    EXPECT_FALSE(obj3.has_value());

    // 释放一个对象
    obj1 = std::nullopt;
    EXPECT_EQ(pool.available(), 1);

    // 现在应该能够再次获取对象
    obj3 = pool.acquire();
    ASSERT_TRUE(obj3.has_value());
}

// 并发安全性测试
TEST(ObjectPoolTest, ThreadSafety) {
    constexpr size_t POOL_SIZE = 1000;
    constexpr size_t NUM_THREADS = 4;
    constexpr size_t OPERATIONS_PER_THREAD = 10000;

    ObjectPool<TestObject, POOL_SIZE> pool;
    std::atomic<size_t> successful_acquisitions{0};
    std::atomic<size_t> failed_acquisitions{0};

    auto worker = [&]() {
        for (size_t i = 0; i < OPERATIONS_PER_THREAD; ++i) {
            auto obj = pool.acquire();
            if (obj) {
                // 模拟使用对象
                obj.value()->setValue(i);
                std::this_thread::yield();
                EXPECT_EQ(obj.value()->getValue(), i);
                successful_acquisitions++;
            } else {
                failed_acquisitions++;
            }
        }
    };

    std::vector<std::thread> threads;
    for (size_t i = 0; i < NUM_THREADS; ++i) {
        threads.emplace_back(worker);
    }

    for (auto& thread : threads) {
        thread.join();
    }

    EXPECT_EQ(pool.available(), POOL_SIZE);
    std::cout << "Successful acquisitions: " << successful_acquisitions << std::endl;
    std::cout << "Failed acquisitions: " << failed_acquisitions << std::endl;
}

// 性能测试：对象池 vs 标准分配器
TEST(ObjectPoolTest, PerformanceBenchmark) {
    constexpr size_t POOL_SIZE = 1000;
    constexpr size_t NUM_OPERATIONS = 100000;

    ObjectPool<TestObject, POOL_SIZE> pool;
    std::vector<std::chrono::nanoseconds> pool_times;
    std::vector<std::chrono::nanoseconds> heap_times;

    // 测试对象池性能
    {
        auto start = std::chrono::high_resolution_clock::now();
        for (size_t i = 0; i < NUM_OPERATIONS; ++i) {
            auto obj = pool.acquire();
            if (obj) {
                obj.value()->setValue(i);
            }
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = end - start;
        std::cout << "Object pool average time per operation: "
                  << std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() / NUM_OPERATIONS
                  << " ns" << std::endl;
    }

    // 测试标准分配器性能
    {
        auto start = std::chrono::high_resolution_clock::now();
        for (size_t i = 0; i < NUM_OPERATIONS; ++i) {
            auto obj = std::make_unique<TestObject>();
            obj->setValue(i);
        }
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = end - start;
        std::cout << "Standard allocator average time per operation: "
                  << std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() / NUM_OPERATIONS
                  << " ns" << std::endl;
    }
}

// 移动语义测试
TEST(ObjectPoolTest, MoveSemantics) {
    ObjectPool<TestObject, 4> pool;

    // 测试移动构造
    auto obj1 = pool.acquire();
    ASSERT_TRUE(obj1.has_value());
    obj1.value()->setValue(42);

    auto obj2 = std::move(obj1);
    EXPECT_FALSE(obj1.has_value());  // NOLINT
    ASSERT_TRUE(obj2.has_value());
    EXPECT_EQ(obj2.value()->getValue(), 42);

    // 测试移动赋值
    auto obj3 = pool.acquire();
    ASSERT_TRUE(obj3.has_value());
    obj3.value()->setValue(24);

    obj2 = std::move(obj3);
    EXPECT_FALSE(obj3.has_value());  // NOLINT
    ASSERT_TRUE(obj2.has_value());
    EXPECT_EQ(obj2.value()->getValue(), 24);
}

// 对象重用测试
TEST(ObjectPoolTest, ObjectReuse) {
    ObjectPool<TestObject, 1> pool;

    // 第一次使用
    {
        auto obj = pool.acquire();
        ASSERT_TRUE(obj.has_value());
        obj.value()->setValue(42);
    }

    // 第二次使用应该得到重置后的对象
    {
        auto obj = pool.acquire();
        ASSERT_TRUE(obj.has_value());
        EXPECT_EQ(obj.value()->getValue(), 0);  // 应该被重置为初始值
    }
}